import selectors
import socket
import random

from FPDLCore import MessageDefs
from FPDLCore.BaseServerNet import BaseServerNet


class DownloadWorkerServer(BaseServerNet):

    def __init__(self, entryserver, port):
        BaseServerNet.__init__(self, port)
        self.entryserver = entryserver
        self.workload = 0
        self.rdata = {}
        self.sdata = {}

    def onstart(self):
        print('DownloadWorker started at port:', self.port)
        self.entryserver.registerworker(self)

    def onexit(self):
        print('DownloadWorker exit. port:', self.port)
        self.entryserver.unregisterworker(self)

    def onread(self, conn, data):
        if conn in self.rdata.keys():
            data = self.rdata[conn] + data
        request = MessageDefs.deserialize(data)
        if request:
            if conn in self.rdata.keys():
                del self.rdata[conn]
            self.handlerequest(conn, request)
        else:
            self.rdata[conn] = data

    def onsend(self, conn):
        if conn in self.sdata.keys():
            data = self.sdata[conn]
            sended = conn.send(data)

            if sended < len(data):
                self.sdata[conn] = data[sended:]
            else:
                del self.sdata[conn]
                self.waitread(conn)
        else:
            self.waitread(conn)

    def onclose(self, conn):
        self.workload -= 1
        if conn in self.rdata.keys():
            del self.rdata[conn]
        if conn in self.sdata.keys():
            del self.sdata[conn]
        conn.close()

    def handlerequest(self, conn, request):
        try:
            print("handlerequest", request)
            with open(request.filepath, 'rb') as file:
                file.seek(request.begpos)
                data = file.read(request.endpos - request.begpos)
                self.waitsend(conn)
        except OSError as e:
            print("error handlerequest:request-", request, "exception-", e)
            data = None
        self.workload += 1
        if data is None or len(data) != request.endpos - request.begpos:
            self.sdata[conn] = b'\x00' # Error
        else:
            self.sdata[conn] = bytes([random.randint(1,255)]) + data # OK
        self.waitsend(conn)